#include "sdShip.h"

void sdShip::move(const cpVect& direction) {
	cpFloat angle = body_->a;
	
	//TODO: CHANGE ALL SIN() COS() TO A TABLE FOR FASTER SPEED
	cpFloat c = cos(angle);
	cpFloat s = -sin(angle);
	
	cpVect force = cpv(0, 0);
	if(direction.x < 0) {
		force.x += direction.x * leftForce_ * c;
		force.y += -direction.x * leftForce_ * s;
	} else {
		force.x += direction.x * rightForce_ * c;
		force.y += -direction.x * rightForce_ * s;
	}
	
	if(direction.y < 0) {
		force.x += direction.y * reverseForce_ * s;
		force.y += direction.y * reverseForce_ * c;
	} else {
	    force.x += direction.y * forwardsForce_ * s;
		force.y += direction.y * forwardsForce_ * c;
	}
	
	body_->f = force;
}

void sdShip::turn(const cpVect& direction) {
	cpFloat shipToMouseAngle = -cpvtoangle(cpvsub(direction, body_->p));
	cpFloat turn = (shipToMouseAngle - body_->a);
	
    if(turn > 3.14159) {
        turn -= (2 * 3.14159);
    } else if(turn < -3.14159) {
        turn += (2 * 3.14159);
    }
    
    turn *= deltaW_;

	body_->w = turn;
}

void sdShip::update(cpFloat ticks) {
	for(int i = 0; i < guns; i++) {
		if(gunTimes_[i] > 0) {
			gunTimes_[i] -= ticks;
		}
	}
}

bool sdShip::shoot(const int weapon, std::set<sdTimed*>* bullets) {
	if(weapon < 0 || weapon >= guns) {
		return false;
	}

	if(gunTimes_[weapon] > 0) {
			return false;
	}
	gunTimes_[weapon] = gunReloads_[weapon];
	
	if(weapon == 0) {
        int num = 4;
        cpVect verts[] = {
    		cpv(-0.1, -15),
    		cpv(-0.1,  15),
    		cpv( 0.1,  15),
    		cpv( 0.1, -15),
    	};
		
		cpBody* body = new cpBody();

		sdTimed* bullet = new sdTimed(2.0, body);
		bullet->setMass(20.0);
		bullet->setPos(cpv(body_->p.x + (15 * sin(-body_->a)), body_->p.y + (15 * cos(-body_->a))));
    	bullet->addPolyShape(num, verts, cpvzero, 2);
		bullet->setAngle(body_->a);
    	bullet->setVel(cpv(2000 * sin(-body_->a), 2000 * cos(-body_->a)));
 	
    	bullets->insert(bullet);
    	return true;
    } else if(weapon == 1) {
		int num = 4;
        cpVect verts[] = {
    		cpv(-0.1, -20),
    		cpv(-0.1,  20),
    		cpv( 0.1,  20),
    		cpv( 0.1, -20),
    	};
		
		int count = 30;
		cpFloat spread = 20;
		spread /= 2;
		cpFloat spreadStart = -(spread / 180) * 3.14159;
		cpFloat spreadStep = -(spreadStart * 2) / (count - 1);
		cpFloat direction;
		
		for(int i = 0; i < count; i++) {
			cpBody* body = new cpBody();
			
			direction = i * spreadStep;

			sdTimed* bullet = new sdTimed(2.0, body);
			bullet->setMass(20.0);
			bullet->setPos(cpv(body_->p.x + (15 * sin(-body_->a)), body_->p.y + (15 * cos(-body_->a))));
    		bullet->addPolyShape(num, verts, cpvzero, 2);
			bullet->setAngle(body_->a - spreadStart - direction);
    		bullet->setVel(cpv(2000 * sin(-body_->a + spreadStart + direction),
				               2000 * cos(-body_->a + spreadStart + direction)));
	 	
    		bullets->insert(bullet);
		}
		return true;
    } else if(weapon == 2) {
		int num = 4;
        cpVect verts[] = {
    		cpv(-0.1, -20),
    		cpv(-0.1,  20),
    		cpv( 0.1,  20),
    		cpv( 0.1, -20),
    	};
		
		int count = 100;
		cpFloat spread = 360;
		spread /= 2;
		cpFloat spreadStart = -(spread / 180) * 3.14159;
		cpFloat spreadStep = -(spreadStart * 2) / (count - 1);
		cpFloat direction;
		
		for(int i = 0; i < count; i++) {
			cpBody* body = new cpBody();
			
			direction = i * spreadStep;

			sdTimed* bullet = new sdTimed(2.0, body);
			bullet->setMass(20.0);
			bullet->setPos(cpv(body_->p.x + (15 * sin(-body_->a)), body_->p.y + (15 * cos(-body_->a))));
    		bullet->addPolyShape(num, verts, cpvzero, 2);
			bullet->setAngle(body_->a - spreadStart - direction);
    		bullet->setVel(cpv(2000 * sin(-body_->a + spreadStart + direction),
				               2000 * cos(-body_->a + spreadStart + direction)));
	 	
    		bullets->insert(bullet);
    		
		}
		return true;
	}
    
    return false;
}

void sdShip::getChunks(std::set<sdTimed*>* chunks) {
    int count = 150;
    cpFloat div = 2 * 3.14159 / count;
    cpFloat iDiv;
    
    for(int i = 0; i < count; i++) {
        cpBody* body = new cpBody();
        iDiv = i * div;
        sdTimed* bullet = new sdTimed(2.0, body);
        bullet->start();
        bullet->setMass(20.0);
    	bullet->setPos(cpv(body_->p.x + (25 * sin(iDiv)), body_->p.y + (25 * cos(iDiv))));
    	bullet->addCircleShape(0, 4, cpvzero, 4);

    	bullet->setVel(cpv(7000 * sin(iDiv), 7000 * cos(iDiv)));
 	
    	chunks->insert(bullet);
    }
}
